package com.example.xcsubsystem.service;

import com.example.xcsubsystem.util.RemoteHeader;
import com.example.xcsubsystem.vo.OrganizationDTO;
import com.example.xcsubsystem.vo.OrganizationUserDTO;
import com.example.xcsubsystem.vo.RemoteUserDTO;
import com.example.xcsubsystem.vo.UserDTO;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Nonnull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.util.*;


/**
 * 2024/9/28
 * 远程调用统一平台提供的接口
 * 接口调用约定：http header 中需加入appKey appSecret 和 iv 向量
 * 其中秘钥是经过加密的
 * iv自动随机生成的，并参与加密秘钥的过程，iv经过Base64编码成字符后加入到header中
 * <code>
 *     RemoteHeader headers = RemoteHeader.getInstance(appKey, appSecret);
 *     HttpRequest httpRequest = HttpRequest.newBuilder()
 *                 .uri(URI.create(urlBuilder.toString()))
 *                 .setHeader(RemoteHeader.APPKEY, headers.getAppKey())
 *                 .setHeader(RemoteHeader.APPSECRET, headers.getAppSecret())
 *                 .setHeader(RemoteHeader.IV, headers.getIv())
 *                 .GET()
 *                 .build();
 * </code>
 *
 * @author fengyu
 */
@Service
public class RemoteService {
    private static final Logger log = LoggerFactory.getLogger(RemoteService.class);
    /**
     * token验证接口地址
     */
    @Value("${remote.url.token}")
    private String tokenUrl;

    /**
     * 用户同步接口地址，全量同步或增量同步由具体参数指定
     */
    @Value("${remote.url.pushUser}")
    private String pushUserUrl;

    /**
     * 个人访问权限变更接口地址
     */
    @Value("${remote.url.updateUser}")
    private String updateUserUrl;

    /**
     * 服务审批反馈接口地址
     */
    @Value("${remote.url.approvalStatus}")
    private String approvalStatusUrl;

    /**
     * 工作通知推送接口地址
     */
    @Value("${remote.url.sendWorkMessage}")
    private String workMsgUrl;

    /**
     * 站内信推送接口地址
     */
    @Value("${remote.url.sendUserMessage}")
    private String userMsgUrl;

    /**
     * 获取全部浙政钉组织机构接口地址
     */
    @Value("${remote.url.getAllOrganization}")
    private String allOrganizationUrl;

    /**
     * 获取下一级浙政钉组织机构接口地址
     */
    @Value("${remote.url.getSubOrganization}")
    private String subOrganizationUrl;

    /**
     * 获取组织机构内所有浙政钉用户信息接口地址
     */
    @Value("${remote.url.getOrganizationUsers}")
    private String organizationUsersUrl;

    /**
     * 调用统一平台token验证接口，获取用户信息
     * @param appKey 系统标识
     * @param appSecret 秘钥
     * @param token 单点登录接口获取的token
     * @return
     */
    public RemoteUserDTO getUserFromToken (@Nonnull final String appKey, @Nonnull final String appSecret, @Nonnull final String token) throws Exception {
        // 生成SM4加密向量iv，并对子系统的 appSecret 进行加密
        RemoteHeader headers = RemoteHeader.getInstance(appKey, appSecret);
        RemoteUserDTO userDTO;
        // 构建带参数的 URL
        StringBuilder urlBuilder = new StringBuilder(tokenUrl);

        urlBuilder.append("?").append("token=").append(token);
        log.info(urlBuilder.toString());
        HttpClient httpClient = HttpClient.newHttpClient();
        HttpRequest httpRequest = HttpRequest.newBuilder()
                .uri(URI.create(urlBuilder.toString()))
                .setHeader(RemoteHeader.APPKEY, headers.getAppKey())
                .setHeader(RemoteHeader.APPSECRET, headers.getAppSecret())
                .setHeader(RemoteHeader.IV, headers.getIv())
                .GET()
                .build();
        HttpResponse<String> httpResponse = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8));
        httpResponse.body();

        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode jsonNode = objectMapper.readTree(httpResponse.body());
        int code = jsonNode.get("code").asInt();
        switch (code) {
            case 200:
                log.info("解析返回的用户信息");
                userDTO = objectMapper.treeToValue(jsonNode.get("data"), RemoteUserDTO.class);
                // todo 得到用户信息，做进一步处理
                log.info("获取到用户信息： {}",userDTO.getLastName());
                return userDTO;
            case 404:
                log.info("{},{}",code, jsonNode.get("message").asText());
        }
        return null;
    }

    /**
     * 将本系统用户推送给统一平台 ，当参数cover为true时，表示全量更新用户，false时增量更新
     * @param appKey appKey
     * @param appSecret appSecret
     * @param cover 是否全量更新，即本系统所有浙政钉用户
     * @param users 用户信息包括浙政钉ID和是否允许访问系统
     * @return code 200 表示成功
     */
    public boolean pushUsers(@Nonnull final String appKey, @Nonnull final String appSecret, boolean cover, @Nonnull List<UserDTO> users) throws Exception {
        // appSecret加密
        RemoteHeader headers = RemoteHeader.getInstance(appKey, appSecret);
        HashMap<String, Object> params = new HashMap<>();
        params.put("cover", cover);
        params.put("users", users);
        ObjectMapper objectMapper = new ObjectMapper();
        String requestBody = objectMapper.writeValueAsString(params);
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(pushUserUrl))
                .setHeader(RemoteHeader.APPKEY, headers.getAppKey())
                .setHeader(RemoteHeader.APPSECRET, headers.getAppSecret())
                .setHeader(RemoteHeader.IV, headers.getIv())
                .POST(HttpRequest.BodyPublishers.ofString(requestBody, StandardCharsets.UTF_8))
                .header("Content-Type", "application/json")
                .build();

        HttpClient client = HttpClient.newHttpClient();
        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
        JsonNode jsonNode = objectMapper.readTree(response.body());
        int code = jsonNode.get("code").asInt();
        if (200 == code) {
            log.info("推送成功");
            return true;
        } else {
            log.info("推送用户信息失败：{}", code);
            return false;
        }
    }

    /**
     * 当本系统增加或修改某用户的访问权限时，调用接口通知给统一平台*
     * @param appKey appKey
     * @param appSecret appSecret
     * @param accountId 浙政钉ID
     * @param status 1：允许访问本系统， 0：不允许
     * @return true通知成功
     */
    public boolean updateUser(@Nonnull final String appKey, @Nonnull final String appSecret, @Nonnull final String accountId, @Nonnull final int status) throws Exception {
        // appSecret 加密
        RemoteHeader headers = RemoteHeader.getInstance(appKey, appSecret);
        HashMap<String, Object> params = new HashMap<>();
        params.put("accountId", accountId);
        params.put("status", status);
        ObjectMapper objectMapper = new ObjectMapper();
        String requestBody = objectMapper.writeValueAsString(params);
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(updateUserUrl))
                .setHeader(RemoteHeader.APPKEY, headers.getAppKey())
                .setHeader(RemoteHeader.APPSECRET, headers.getAppSecret())
                .setHeader(RemoteHeader.IV, headers.getIv())
                .POST(HttpRequest.BodyPublishers.ofString(requestBody, StandardCharsets.UTF_8))
                .header("Content-Type", "application/json")
                .build();

        HttpClient client = HttpClient.newHttpClient();
        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
        JsonNode jsonNode = objectMapper.readTree(response.body());
        int code = jsonNode.get("code").asInt();
        if (200 == code) {
            log.info("推送成功");
            return true;
        } else {
            log.info("推送用户信息失败：{}", code);
            return false;
        }
    }

    /**
     * 用户申请的服务审批通过后，需调用接口通知统一平台并传递相关信息
     * @param appKey appKey
     * @param appSecret 秘钥
     * @param accountId 用户浙政钉ID
     * @param sid 服务在同一平台端的id
     * @param content json格式的服务信息，可包括服务说明，生成的秘钥等
     * @return true通知成功
     */
    public boolean approvalStatus(@Nonnull final String appKey,
                                @Nonnull final String appSecret,
                                @Nonnull final String accountId,
                                @Nonnull final String sid,
                                @Nonnull final String content) throws Exception {
        // 加密appSecret
        RemoteHeader headers = RemoteHeader.getInstance(appKey, appSecret);
        HashMap<String, Object> params = new HashMap<>();
        params.put("accountId", accountId);
        params.put("sid", sid);
        params.put("content", content);
        ObjectMapper objectMapper = new ObjectMapper();
        String requestBody = objectMapper.writeValueAsString(params);
        HttpRequest request = HttpRequest.newBuilder()
                .setHeader(RemoteHeader.APPKEY, headers.getAppKey())
                .setHeader(RemoteHeader.APPSECRET, headers.getAppSecret())
                .setHeader(RemoteHeader.IV, headers.getIv())
                .setHeader("Content-Type", "application/json")
                .uri(URI.create(approvalStatusUrl))
                .POST(HttpRequest.BodyPublishers.ofString(requestBody, StandardCharsets.UTF_8))
                .build();

        HttpClient client = HttpClient.newHttpClient();
        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
        JsonNode jsonNode = objectMapper.readTree(response.body());
        int code = jsonNode.get("code").asInt();
        if (200 == code) {
            log.info("推送成功");
            return true;
        } else {
            log.info("推送失败：{}", code);
            return false;
        }

    }

    /**
     * 系统内部发送站内信时，调用接口通知统一平台
     * @param appKey appKey
     * @param appSecret appSecret
     * @param senderId 发送者浙政钉id
     * @param message 信息内容，文本格式
     * @param receiverId 接收方浙政钉id
     * @return true通知成功
     */
    public boolean sendMessage(@Nonnull final String appKey,
                               @Nonnull final String appSecret,
                               @Nonnull final String senderId,
                               @Nonnull final String message,
                               @Nonnull final String receiverId) throws Exception {
        //  加密appSecret
        RemoteHeader headers = RemoteHeader.getInstance(appKey, appSecret);
        HashMap<String, Object> params = new HashMap<>();
        params.put("senderId", senderId);
        params.put("message", message);
        params.put("receiverId", receiverId);
        ObjectMapper objectMapper = new ObjectMapper();
        String requestBody = objectMapper.writeValueAsString(params);
        HttpRequest request = HttpRequest.newBuilder()
                .setHeader(RemoteHeader.APPKEY, headers.getAppKey())
                .setHeader(RemoteHeader.APPSECRET, headers.getAppSecret())
                .setHeader(RemoteHeader.IV, headers.getIv())
                .setHeader("Content-Type", "application/json")
                .uri(URI.create(userMsgUrl))
                .POST(HttpRequest.BodyPublishers.ofString(requestBody, StandardCharsets.UTF_8))
                .build();

        HttpClient client = HttpClient.newHttpClient();
        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
        JsonNode jsonNode = objectMapper.readTree(response.body());
        int code = jsonNode.get("code").asInt();
        if (200 == code) {
            log.info("推送成功");
            return true;
        } else {
            log.info("推送失败：{}", code);
            return false;
        }
    }

    /**
     * 系统内部发送工作工作，调用接口通知统一平台
     * @param appKey appKey
     * @param appSecret appSecret
     * @param receiverIds 接收方浙政钉id，多个接受者以英文逗号分隔
     * @param message 信息内容，文本格式
     * @param sendToApp 是否将消息推送到浙政钉APP
     * @return true通知成功
     */
    public boolean sendWorkMessage(@Nonnull final String appKey,
                               @Nonnull final String appSecret,
                               @Nonnull final String receiverIds,
                               @Nonnull final String message,
                               @Nonnull final boolean sendToApp) throws Exception {
        // 加密appSecret
        RemoteHeader headers = RemoteHeader.getInstance(appKey, appSecret);
        HashMap<String, Object> params = new HashMap<>();
        params.put("sendToApp", sendToApp);
        params.put("message", message);
        params.put("receiverIds", receiverIds);
        ObjectMapper objectMapper = new ObjectMapper();
        String requestBody = objectMapper.writeValueAsString(params);
        HttpRequest request = HttpRequest.newBuilder()
                .setHeader(RemoteHeader.APPKEY, headers.getAppKey())
                .setHeader(RemoteHeader.APPSECRET, headers.getAppSecret())
                .setHeader(RemoteHeader.IV, headers.getIv())
                .setHeader("Content-Type", "application/json")
                .uri(URI.create(workMsgUrl))
                .POST(HttpRequest.BodyPublishers.ofString(requestBody, StandardCharsets.UTF_8))
                .build();

        HttpClient client = HttpClient.newHttpClient();
        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
        JsonNode jsonNode = objectMapper.readTree(response.body());
        int code = jsonNode.get("code").asInt();
        if (200 == code) {
            log.info("推送成功");
            return true;
        } else {
            log.info("推送失败：{}", code);
            return false;
        }
    }

    /**
     * 获取浙政钉全部组织机构信息
     * @param appKey appKey
     * @param appSecret appSecret
     * @return OrganizationDTO
     * @throws Exception
     */
    public List<OrganizationDTO> getAllOrganization(@Nonnull final String appKey,
                                      @Nonnull final String appSecret ) throws Exception {
        // 加密appSecret
        RemoteHeader headers = RemoteHeader.getInstance(appKey, appSecret);

        ObjectMapper objectMapper = new ObjectMapper();

        HttpRequest request = HttpRequest.newBuilder()
                .setHeader(RemoteHeader.APPKEY, headers.getAppKey())
                .setHeader(RemoteHeader.APPSECRET, headers.getAppSecret())
                .setHeader(RemoteHeader.IV, headers.getIv())
                .uri(URI.create(allOrganizationUrl))
                .GET()
                .build();

        HttpClient client = HttpClient.newHttpClient();
        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
        JsonNode jsonNode = objectMapper.readTree(response.body());
        int code = jsonNode.get("code").asInt();
        if (200 == code) {
            log.info("获取全部组织机构信息成功，接着处理......");
            List<OrganizationDTO> list = objectMapper.treeToValue(jsonNode.get("data"), ArrayList.class);
            // todo 解析json获取组织结构
            return list;
        } else {
            log.info("获取全部组织机构信息失败：{}", code);
            return null;
        }
    }

    /**
     * 获取浙政钉指定组织机构内部下级组织机构信息
     * @param appKey appKey
     * @param appSecret appSecret
     * @param orgCode 本机组织code
     * @return OrganizationDTO
     * @throws Exception
     */
    public List<OrganizationDTO> getSubOrganization(@Nonnull final String appKey,
                                              @Nonnull final String appSecret,
                                              String orgCode) throws Exception {
        // 加密appSecret
        RemoteHeader headers = RemoteHeader.getInstance(appKey, appSecret);

        ObjectMapper objectMapper = new ObjectMapper();

        HttpRequest request = HttpRequest.newBuilder()
                .setHeader(RemoteHeader.APPKEY, headers.getAppKey())
                .setHeader(RemoteHeader.APPSECRET, headers.getAppSecret())
                .setHeader(RemoteHeader.IV, headers.getIv())
                .uri(URI.create(subOrganizationUrl + "?orgCode=" + orgCode))
                .GET()
                .build();

        HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
        JsonNode jsonNode = objectMapper.readTree(response.body());
        int code = jsonNode.get("code").asInt();
        if (200 == code) {
            log.info("获取子组织机构信息成功，接着处理......");
            List<OrganizationDTO> list = objectMapper.treeToValue(jsonNode.get("data"), ArrayList.class);
            // todo 解析json获取组织机构
            return list;
        } else {
            log.info("获取子机构信息失败：{}", code);
            return null;
        }
    }

    /**
     * 获取浙政钉组织结构内用户信息
     * @param appKey appKey
     * @param appSecret appSecret
     * @param organizationCode 浙政钉组织机构代码
     * @return List<OrganizationUserDTO>
     * @throws Exception
     */
    public List<OrganizationUserDTO> getOrganizationUsers(@Nonnull final String appKey,
                                                          @Nonnull final String appSecret,
                                                          @Nonnull final String organizationCode) throws Exception {
        // 加密appSecret
        RemoteHeader headers = RemoteHeader.getInstance(appKey, appSecret);

        ObjectMapper objectMapper = new ObjectMapper();

        HttpRequest request = HttpRequest.newBuilder()
                .setHeader(RemoteHeader.APPKEY, headers.getAppKey())
                .setHeader(RemoteHeader.APPSECRET, headers.getAppSecret())
                .setHeader(RemoteHeader.IV, headers.getIv())
                .uri(URI.create(organizationUsersUrl + "?organizationCode=" + organizationCode))
                .GET()
                .build();

        HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
        JsonNode jsonNode = objectMapper.readTree(response.body());
        int code = jsonNode.get("code").asInt();
        if (200 == code) {
            log.info("获取全部组织机构信息成功，接着处理......");
            List<OrganizationUserDTO> list = objectMapper.treeToValue(jsonNode.get("data"), ArrayList.class);
            // todo 解析json获取浙政钉组织内用户
            return list;
        } else {
            log.info("获取组织机构内部用户信息失败：{}", code);
            return null;
        }

    }
}
